/**
 * File name: AbstractARFFFileWriter.java Author: Willard Wang Create date: Jul
 * 28, 2013
 */
package edu.sjtu.se.prophet.io;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

import edu.sjtu.se.prophet.graph.Graph;

/**
 * @author deathspeeder
 * 
 */
public abstract class AbstractARFFFileWriter implements GraphWriter {
    protected static String[] VALID_METRICS = new String[] { "CountInput",
            "CountLineCode", "CountOutput", "CountPath", "Cyclomatic",
            "Essential", "MaxNesting", "RatioCommentToCode" };

    protected BufferedWriter br;
    protected float depth;
    protected int count;
    protected List<Graph> graphs;
    protected String outFileName = "data.arff";
    protected String arffName = "replace me";

    /*
     * (non-Javadoc)
     * 
     * @see edu.sjtu.se.prophet.io.GraphWriter#init(java.util.List)
     */
    @Override
    public void init(List<Graph> graphs) {
        this.graphs = graphs;
    }

    /*
     * (non-Javadoc)
     * 
     * @see edu.sjtu.se.prophet.io.GraphWriter#setValue(java.lang.String,
     * java.lang.String)
     */
    @Override
    public void setValue(String key, String value) {
        if ("depth".equals(key)) {
            depth = Float.parseFloat(value);
        } else if ("count".equals(key)) {
            count = Integer.parseInt(value);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see edu.sjtu.se.prophet.io.GraphWriter#wirte()
     */
    @Override
    public void wirte() throws IOException {
        br = new BufferedWriter(new FileWriter(new File(outFileName)));
        writeHeaders(arffName);
        writeData();
        br.close();
    }

    /**
     * @throws IOException
     * 
     */
    protected abstract void writeData() throws IOException;

    /**
     * @param string
     * @throws IOException
     */
    private void writeHeaders(String name) throws IOException {

        br.append("@RELATION " + name + "\n");
        for (int i = 0; i < VALID_METRICS.length; i++) {
            br.append("@ATTRIBUTE " + VALID_METRICS[i] + " NUMERIC\n");
        }
        StringBuffer buffer = new StringBuffer();
        for (int i = 1; i <= count; i++) {
            buffer.append("Level" + i + ",");
        }
        if (buffer.length() > 0)
            buffer.deleteCharAt(buffer.length() - 1);
        br.append("@ATTRIBUTE Bugs {" + buffer.toString() + "}\n");
        br.flush();
    }

    /**
     * @param averageMetric
     * @return
     */
    protected String getLevel(float avgBug) {
        for (int i = 1; i <= count; i++) {
            if (avgBug < depth * i)
                return "Level" + i;
        }
        return "Level" + count;
    }
}
